﻿using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Network
{
	/// <summary>
	/// UDP广播发送端
	/// </summary>
	public class BroadcastServer
	{
		Socket socket;
		IPEndPoint ipe;
		byte[] data;
		public bool broadcasting;
		Thread thread;

		public BroadcastServer(int port)
		{
			socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
			socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
			ipe = new IPEndPoint(IPAddress.Broadcast, port);
			broadcasting = false;
		}

		public void StartBroadcasting(string strData)
		{
			byte[] data = Encoding.UTF8.GetBytes(strData);
			StartBroadcasting(data);
		}
		public void StartBroadcasting(byte[] data)
		{
			thread?.Abort();
			this.data = data;
			broadcasting = true;
			thread = new Thread(Broadcast);
			thread.Start();
		}

		public void EndBroadcasting() { broadcasting = false; thread?.Abort(); }
		public void Close()
		{
			broadcasting = false;
			thread?.Abort();
			socket.Close();
		}
		void Broadcast()
		{
			while (broadcasting)
			{
				socket.SendTo(data, ipe);
				Thread.Sleep(2000);
			}
		}
	}

	/// <summary>
	/// UDP广播接收端
	/// </summary>
	public class BroadcastClient
	{
		Socket socket;
		byte[] data;
		Thread thread;
		System.Action<string> callback;
		public bool listening = false;
		public BroadcastClient(int port, System.Action<string> callback)
		{
			socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
			IPEndPoint ipe = new IPEndPoint(IPAddress.Any, port);
			socket.Bind(ipe);
			data = new byte[2048];
			this.callback = callback;
		}
		public void StartListening()
		{
			listening = true;
			thread?.Abort();
			thread = new Thread(Listen);
			thread.Start();
		}
		public void Close()
		{
			listening = false;
			thread?.Abort();
			socket.Close();
		}
		void Listen()
		{
			while (listening)
			{
				int recvCnt = socket.Receive(data);
				string strData = Encoding.UTF8.GetString(data, 0, recvCnt);
				callback?.Invoke(strData);
			}
		}
	}
}
